<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>JSDoc: Source: globals.js</title>
    
    <script src="scripts/prettify/prettify.js"> </script>
    <script src="scripts/prettify/lang-css.js"> </script>
    <!--[if lt IE 9]>
      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>

<body>

<div id="main">
    
    <h1 class="page-title">Source: globals.js</h1>
    
    


    
    <section>
        <article>
            <pre class="prettyprint source"><code>/**
 * @file define global functions which are used with high frequency
 */

var path = require('path');
var fs = require('fs');
var _ = require('underscore');
var thunkify = require('thunkify');
var co = require('co');

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @param {String} s *, ABC
 * @return {String} Trimmed string
 * @desc Trim a string and return new one. If pass nothing or null to this function, returns an empty string
 * @throws {TypeError} When parameter s is not a string
 * @example
 * var s = '   abc   ';
 * console.log(trim(s));              //print: abc
 * console.log(trim(null));         //print: ''-> a blank string
 * */
trim = function (s) {
        s = s || '';
        if (typeof s == 'string') {
                return s.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
        }
        throw new TypeError('Not a string');
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @return {String} Home directory of EasyNode
 * @desc Get the home directory of EasyNode. By default, returns the parent directory of  process.pwd(), but also you can set a command
 * line argument to specify where the home directory of EasyNode is.
 * @example
 * console.log(home());              //print: /home/zlbbq/EasyNode,  make sure your working directory is $EasyNode/bin
 *
 * //if you start EasyNode and passed command line argument 'easynode-home'
 * nodejs /home/zlbbq/EasyNode/bin/main.js --easynode-home=/home/zlbbq/EasyNode
 *
 * console.log(home());             //print: /home/zlbbq/EasyNode
 * */
home = function () {
        return arg('easynode-home') || path.join(process.cwd(), '../');
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @param {String} p Relative path to any resource in EasyNode, relative to the home directory of EasyNode.
 * @see home
 * @return {String} Absolute path of passed resource.
 * @desc Get the home directory of EasyNode. By default, returns the parent directory of  process.pwd(), but also you can set a command
 * line argument to specify where the home directory of EasyNode is.
 * @example
 * console.log(real('src/');              //print: /home/zlbbq/EasyNode/src
 * */
real = function (p) {
        return path.join(home(), p || '');
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @desc This function is a shortcut to 'extend' of underscore.
 * @example
 *
 *  var o = { a : 'a'};
 *  extend(o, {b : 'b'});
 *  console.log(JSON.stringify(o));             //print: {a : 'a', b: 'b'}
 * */
extend = function () {
        _.extend.apply(null, arguments);
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @param {String} name *, Name of command line argument
 * @return {String} Value of command line argument
 * @desc Get command line argument
 * @example
 *
 * nodejs main.js --easynode-home=/home/zlbbq/EasyNode
 * console.log(arg('easynode-home'));           //print: /home/zlbbq/EasyNode
 * */
arg = function (name) {
        if (!global._parsed_args) {
                global._parsed_args = {};
                var f = false;
                var argReg = /^\-\-(.*)=(.*)$/;
                process.argv.forEach(function (val) {
                        if (!f) {
                                if (val.match(/^\.\/.*\.js$/) || val.match(/^.*\.js$/)) {
                                        f = true;
                                }
                        }
                        else {
                                var p = argReg.exec(val);
                                if (p) {
                                        global._parsed_args[p[1]] = p[2];
                                }
                        }
                });
        }
        return global._parsed_args[name || ''];
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @param {String} name *, Name of configuration item
 * @return {String} Value of configuration item or null if configuration item not exists
 * @desc Get configuration value, configuration file is $EasyNode/etc/EasyNode.conf. Note : if a command line argument has the same
 * name as configuration item, the configuration item in EasyNode.conf is ignored, means, the return value is equal to arg().
 * */
config = function (name) {
        if (!global._config_cache) {
                global._config_cache = {};
                var cfg = fs.readFileSync(real('etc/EasyNode.conf'));
                cfg = cfg.toString().split('\n');
                cfg.forEach(function (c) {
                        if (c && c[0] != '#') {          //#is a comment flag
                                c = c.split('=');
                                c[0] = c[0] && trim(c[0]);
                                c[1] = c[1] && trim(c[1]);
                                if (c[0]) {
                                        global._config_cache[c[0]] = c[1];
                                }
                        }
                });
        }
        var v = global._config_cache[name];
        //command line argument can overwrite EasyNode.conf
        var clv = arg(name);
        return clv ? clv : v;
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @param {String} name *, pass __dirname or __filename
 * @return {String} Namespace descriptor
 * @desc Get namespace of source code, Note :  the source code folder is $EasyNode/src/
 * @example
 * //supposing the following code is written in file $EasyNode/src/easynode/util/StringUtil.js
 *
 * console.log(namespace(__filename));  //print easynode.util.StringUtil
 * console.log(namespace(__dirname));   //print easynode.util
 * */
namespace = function (name) {
        name = name.replace(/\.js/, '');
        var src = real('src/');
        return name.substring(src.length).replace(/\//gm, '.');
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @param {String} name *, Class name or namespace name
 * @return {Object} Namespace instance or node export instance
 * @desc Use a class or use classes of a namespace
 * @example
 * //supposing the following code is written in file $EasyNode/src/easynode/util/StringUtil.js
 *
 * using('easynode.Logger');
 * var logger = easynode.Logger.forFile(__filename);
 * logger.debug('hello');
 *
 * var Logger = using('easynode.Logger');
 * Logger.forFile(__filename).debug('hello');
 *
 *
 * var en = using('easynode.*');
 * en.Logger.forFile(__filename).debug('hello');
 * */
using = function (name) {
        if (!global._ns_resolved) {
                throw new Error('call resolveNamespaces firstly!');
        }
        if (typeof name == 'string') {
                var oName = name;
                if (!global._using_cache) {
                        global._using_cache = {};
                }
                if (global._using_cache[name]) {
                        return global._using_cache[name];
                }
                name = name.replace(/\./gm, '/');
                if (name.match(/\/\*$/)) {
                        name = name.replace(/\/\*$/, '');
                        var folder;
                        global._srcFolders.forEach(function (src) {
                                var file = path.join(real(src), name);
                                if (fs.existsSync(file)) {
                                        var fstat = fs.statSync(file);
                                        if (fstat.isDirectory()) {
                                                if (!folder) {
                                                        folder = file;
                                                }
                                                else {
                                                        console.warn('***Warning: Ambiguous resource [' + oName + '], [' + folder + '/*] is found firstly and returns');
                                                }
                                        }
                                }
                        });
                        if (folder) {
                                var files = fs.readdirSync(folder);
                                var o = {};
                                files.forEach(function (f) {
                                        if (f.match(/\.js$/)) {
                                                f = f.replace(/\.js$/, '');
                                                o[f] = require(path.join(folder, f));
                                        }
                                });
                                global._using_cache[oName] = o;
                                return o;
                        }
                        else {
                                throw new Error('Resource [' + oName + '] not found!');
                        }
                }
                else {
                        var o;
                        var f;
                        global._srcFolders.forEach(function (src) {
                                var file = path.join(real(src), name + '.js');
                                if (fs.existsSync(file)) {
                                        var fstat = fs.statSync(file);
                                        if (fstat.isFile()) {
                                                if (!o) {
                                                        o = require(file);
                                                        f = file;
                                                }
                                                else {
                                                        console.warn('***Warning: Ambiguous resource [' + oName + '], [' + f + '] is found firstly and returns');
                                                }
                                        }
                                }
                        });
                        if (!o) {
                                throw new Error('Resource [' + oName + '] not found!');
                        }
                        global._using_cache[oName] = o;
                        return o;
                }
        }
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @see using
 * @see resolveNamespace
 * @param {String} ...  *, Source folder, relative to the home directory of EasyNode
 * @desc Add source folders to EasyNode, EasyNode will find class or namespace from source folders. Default source folder of EasyNode is 'src'
 * @example
 * addSourceFolder('test');
 * */
addSourceFolder = function () {
        if (!global._srcFolders) {
                global._srcFolders = ['src'];
        }
        var arr = _.toArray(arguments);
        arr.forEach(function (v) {
                if (_.isString(v)) {
                        global._srcFolders.push(v);
                }
                else if (_.isArray(v)) {
                        addSourceFolder.apply(null, v);
                }
                else {
                        throw new TypeError('Invalid source folder type!');
                }
        });
};

/**
 * @since 1.0
 * @author zlbbq
 * @global
 * @function
 * @see using
 * @see addSourceFolder
 * @desc Resolve namespaces from source folders. EasyNode always resolve 'src' as a source folder.
 * @example
 *
 * addSourceFolder('test');
 * addSourceFolder('test', 'app');
 * resolveNamespaces();
 * */
resolveNamespaces = function () {
        if (!global._srcFolders) {
                global._srcFolders = ['src'];
        }

        var s = '//============DO NOT MODIFY THIS FILE, IT IS AUTO-GENERATED=============/\n\n';
        var namespaces = [];

        function _gen(root, folder, p) {
                var files = fs.readdirSync(folder);
                files.forEach(function (f) {
                        if (fs.statSync(path.join(folder, f)).isDirectory()) {
                                var ns = (p.length > 0 ? (p + '.') : '') + f;
                                if (!_.contains(namespaces, ns)) {
                                        namespaces.push(ns);
                                        s += '/**\n' +
                                                '* @namespace\n' +
                                                '*/\n';
                                        s += ns + ' = ' + '{};\n\n';
                                }
                                else {
                                        console.warn('***Warning: Duplicate definition of namespace [' + ns + '] in source folder [' + root + ']');
                                }
                                _gen(root, path.join(folder, f), ns);
                        }
                });
        }

        global._srcFolders.forEach(function (src) {
                _gen(src, real(src), '');
        });

        fs.writeFileSync(real('src/namespaces.js'), s);
        require('./namespaces.js');
        global._ns_resolved = true;
};</code></pre>
        </article>
    </section>




</div>

<nav>
    <h2><a href="index.html">Index</a></h2><h3>Classes</h3><ul><li><a href="easynode.Logger.html">Logger</a></li></ul><h3>Namespaces</h3><ul><li><a href="easynode.html">easynode</a></li><li><a href="easynode.framework.html">framework</a></li><li><a href="easynode.framework.server.html">server</a></li><li><a href="easynode.test.html">test</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addSourceFolder">addSourceFolder</a></li><li><a href="global.html#arg">arg</a></li><li><a href="global.html#config">config</a></li><li><a href="global.html#extend">extend</a></li><li><a href="global.html#home">home</a></li><li><a href="global.html#namespace">namespace</a></li><li><a href="global.html#real">real</a></li><li><a href="global.html#resolveNamespaces">resolveNamespaces</a></li><li><a href="global.html#trim">trim</a></li><li><a href="global.html#using">using</a></li></ul>
</nav>

<br clear="both">

<footer>
    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Sat May 09 2015 09:08:52 GMT+0800 (CST)
</footer>

<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
